package sistemaDeLaCarrera;

import alumno.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.Vector;

import Catedras.Catedra;

import docente.*;



import excepciones.AlumnoNoAproboTodasLasCorrelatividadesException;
import excepciones.AlumnoYaInscriptoException;
import excepciones.CatedraNoPerteneceAMateriaException;
import excepciones.CupoLLenoException;
import excepciones.HorariosSuperpuestosException;
import excepciones.MateriaNoFormaParteDelPlanDeEstudioException;

public class Materia {
	private String nombre;
	private Double duracion;
	private String programa; 
	private TipoDeMateria tipoDeMateria;
	private List<String> requisitos = new ArrayList<String>();
	private int creditos;//se calcula teniendo en cuenta la dificultad y la cantidad de horas por semana
	private String dificultad;
	private List<Catedra> catedras = new Vector<Catedra>();
	private Area area;
	
	
	public enum TipoDeMateria{
		PROMOCIONABLE, NO_PROMOCIONABLE, OBLIGATORIA, NO_OBLIGATORIA;
	}
	
	/**
	 * Crear una materia
	 * @param nombre de la materia
	 * @param duracion de la materia
	 * @param programa detalla los temas que dara la materia
	 * @param Tipo de materia (promocionable, no promocionable, obligatoria o no obligatoria)
	 * @param requisitos de material que precisa 
	 * @param dificultad de la materia(facil, medio, dificil)
	 * @param Area en que pertenece la materia
	 */
	public Materia(String nombre, Double duracion, String programa, TipoDeMateria tipoDeMateria, List<String> requisitos, String dificultad, Area area) {
		this.nombre = nombre;
		this.duracion = duracion;
		this.programa = programa;
		this.tipoDeMateria = tipoDeMateria;
		this.requisitos = requisitos;
		this.setDificultad(dificultad);
		this.creditos = this.calcularCredito(dificultad,duracion);
		this.area = area;
	}
	
	public Materia(String nombre) {
		this.nombre = nombre;		
	}
	
  public Materia(String nombre, TipoDeMateria tipo){
    this.nombre = nombre;
    this.tipoDeMateria = tipo;
  }
  
	//COMPORTAMIENTO
	@Override
	public boolean equals(Object o) {
		if(o instanceof Materia)
			return this.nombre == ((Materia)o).getNombre();
		else
			return false;
	}
	
	/**
	 * Comprueba si la catedra pertenece a la materia 
	 * @param catedra
	 * @throws CatedraNoPerteneceAMateriaException
	 */
	public void comprobarQueCatedraPerteneceAMateria(Catedra catedra) throws CatedraNoPerteneceAMateriaException{
		if(!catedras.contains(catedra))
			throw new CatedraNoPerteneceAMateriaException();
		
	}
	
	/**
	 * Comprueba si un alumno tiene aprobadas todas las correlatividades necesarias para
	 * anotarse en la materia
	 * @param alumnoEnCarrera
	 * @throws AlumnoNoAproboTodasLasCorrelatividadesException
	 * @throws MateriaNoFormaParteDelPlanDeEstudioException 
	 */
	public void comprobarQueAlumnoAproboCorrelatividades(AlumnoEnCarrera alumnoEnCarrera) throws AlumnoNoAproboTodasLasCorrelatividadesException, MateriaNoFormaParteDelPlanDeEstudioException{
		List<Materia> correlatividades = alumnoEnCarrera.getPlanDeEstudio().obtenerCorrelativas(this);
		Set<Materia> materiasDelAlumno = alumnoEnCarrera.getMateriasAprobadas().keySet();
		List<Materia> materiasAprobadas = new Vector<Materia>();
		for (Materia materia : materiasDelAlumno) {
			materiasAprobadas.add(materia);
		}
		if (!materiasAprobadas.containsAll(correlatividades))
			throw new AlumnoNoAproboTodasLasCorrelatividadesException();		
	}
	
	/**
	 *Inscribe un alumno a una catedra perteneciente a la materia
	 * @param alumno de la carrera
	 * @param nombre de la catedra
	 * @throws CatedraNoPerteneceAMateriaException
	 * @throws AlumnoNoAproboTodasLasCorrelatividadesException 
	 * @throws MateriaNoFormaParteDelPlanDeEstudioException 
	 * @throws HorariosSuperpuestosException 
	 * @throws CupoLLenoException 
	 * @throws AlumnoYaInscriptoException 
	 */
	public void inscribirAlumno(AlumnoEnCarrera alumnoEnCarrera, Catedra catedra) throws CatedraNoPerteneceAMateriaException, AlumnoNoAproboTodasLasCorrelatividadesException, MateriaNoFormaParteDelPlanDeEstudioException, CupoLLenoException, HorariosSuperpuestosException, AlumnoYaInscriptoException {
		this.comprobarQueCatedraPerteneceAMateria(catedra);
		this.comprobarQueAlumnoAproboCorrelatividades(alumnoEnCarrera);
		catedra.inscribirAlumno(alumnoEnCarrera);
	}
	
	/**
	 * 
	 * @param alumno
	 * @param nombreCatedra
	 * @throws CatedraNoPerteneceAMateriaException
	 */
	public void desinscribirAlumno(AlumnoEnCarrera alumnoEnCarrera, Catedra catedra) throws CatedraNoPerteneceAMateriaException {
		comprobarQueCatedraPerteneceAMateria(catedra);
		catedra.desinscribirAlumno(alumnoEnCarrera);
		
	}	
	
	//JonaK le cambie la visibilidad porque lo necesitaba 
	//para testear coeficiente en alumnoEnCarrera
	public int calcularCredito(String dificultad, Double duracion) {
		//Nota: no eliminar metodo
		if(dificultad == "facil")
			return (int)(duracion % 2);
		if(dificultad == "medio")
			return (int)(duracion % 3);
		if(dificultad == "dificil")
			return (int) (duracion % 4);
		return 0;
	}
	//GETTER AND SETTER

	public List<Catedra> getCatedras() {
		return catedras;
	}

	public void setCatedras(List<Catedra> catedras) {
		this.catedras = catedras;
	}

	public void setNombre(String nombre) {
		this.nombre = nombre;
	}
	
	public String getNombre(){
		return this.nombre;
	}


	public Double getDuracion() {
		return duracion;
	}

	public void setDuracion(Double duracion) {
		this.duracion = duracion;
	}

	public String getPrograma() {
		return programa;
	}

	public void setPrograma(String programa) {
		this.programa = programa;
	}

	public List<String> getRequisitos() {
		return requisitos;
	}

	public void setRequisitos(ArrayList<String> requisitos) {
		this.requisitos = requisitos;
	}

	public int getCreditos() {
		return creditos;
	}

	public void setCreditos(int creditos) {
		this.creditos = creditos;
	}

	public Area getArea() {
		return area;
	}

	public void setArea(Area area) {
		this.area = area;
	}


	public void setDificultad(String dificultad) {
		this.dificultad = dificultad;
	}


	public String getDificultad() {
		return dificultad;
	}
	public TipoDeMateria getTipoDeMateria() {
		return tipoDeMateria;
	}
	public void setTipoDeMateria(TipoDeMateria tipoDeMateria) {
		this.tipoDeMateria = tipoDeMateria;
	}
	public void setRequisitos(List<String> requisitos) {
		this.requisitos = requisitos;
	}

	
}
